﻿#region Copyright
/*  This file is part of opinhost.
 *
 *  opinhost is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  opinhost is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with opinhost.  If not, see <http://www.gnu.org/licenses/>.
 */
#endregion
#region using
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
#endregion

#region server_daemon Namespace
namespace server_daemon
{
    #region Program Class
    class Program
    {
        #region Public Variables
        //Incoming data from the client.
        public static string data = null;
        public static string apppath = Directory.GetCurrentDirectory();
        #endregion

        #region StartListening Function
        public static void StartListening()
        {
            //Data buffer for incoming data.
            byte[] bytes = new Byte[1024];

            //Establish the local endpoint for the socket.
            //Dns.GetHostName returns the name of the
            //host running the application.
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

            //Create a TCP/IP socket.
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            //Bind the socket to the local endpoint and
            //listen for incoming connections.
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(10);

                //Start listening for connections.
                while (true)
                {
                    TextTool.AdvWriteLine("Waiting for a connection...",ConsoleColor.Red, true);
                    TextTool.AdvWriteLine("IP Address: " + ipAddress.ToString(), ConsoleColor.Red, true);
                    TextTool.AdvWriteLine("Port: " + localEndPoint.Port.ToString(), ConsoleColor.Red, true);
                    //Program is suspended while waiting for an incoming connection.
                    Socket handler = listener.Accept();
                    data = null;

                    //An incoming connection needs to be processed.
                    while (true)
                    {
                        bytes = new byte[1024];
                        int bytesRec = handler.Receive(bytes);
                        data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                        if (data.IndexOf("<EOF>") > -1)
                        {
                            break;
                        }
                    }

                    //Show the data on the console.
                    TextTool.AdvWriteLine("Text received : " + data, ConsoleColor.Red, true);

                    //Commands
                    String tempstr;
                    int templin;
                    byte[] msg = null;
                    if (!data.Contains(" "))
                    {
                        switch (data)
                        {
                            case "help<EOF>":
                                tempstr = "Help\r\n" +
                                                 "===================================\r\n" +
                                                 "Command                  Description\r\n" +
                                                 "test                     Test some stuff\r\n" +
                                                 "createusr <user> <pass>  Creates a new User\r\n" +
                                                 "createweb <user> <name>  Assigns a new Website to a User\r\n" +
                                                 "deleteusr <user>         Deletes a User\r\n" +
                                                 "deleteweb <name>         Deletes a Website" +
                                                 "<EOF>";
                                templin = TextTool.CountStringOccurrences(tempstr, "\r\n");
                                templin += 1;
                                msg = Encoding.ASCII.GetBytes(templin.ToString() + "\r\n" + tempstr);
                                break;
                            case "test<EOF>":
                                tempstr = "test\r\n" +
                                                 "===================================\r\n" +
                                                 "Testing OK!" +
                                                 "<EOF>";
                                templin = TextTool.CountStringOccurrences(tempstr, "\r\n");
                                templin += 1;
                                msg = Encoding.ASCII.GetBytes(templin.ToString() + "\r\n" + tempstr);
                                break;
                            case "listusers<EOF>":
                                tempstr = "listusers\r\n" +
                                          "===================================\r\n";
                                templin = 0;
                                string line;
                                int counter = 0;
                                //read the file and add to tempstr with \r\n for each line
                                System.IO.StreamReader file = new System.IO.StreamReader(apppath + @"\server_files\users.sdf");
                                while ((line = file.ReadLine()) != null)
                                {
                                    tempstr += line + "\r\n";
                                    counter++;
                                }
                                file.Close();
                                templin = TextTool.CountStringOccurrences(tempstr, "\r\n");
                                templin += 1;
                                msg = Encoding.ASCII.GetBytes(templin.ToString() + "\r\n" + tempstr);
                                break;
                        }
                    }
                    else
                    {
                        Regex r = new Regex("( )");
                        string[] splitdata = r.Split(data.Replace("<EOF>", ""));
                        Console.WriteLine("Split: " + data.Replace("<EOF>", ""));
                        int count = 0;
                        Console.WriteLine(splitdata.Length);
                        int ran = 1;
                        bool ranbool = false;
                        while (ranbool == false)
                        {
                            Console.WriteLine("Processing: " + ran);
                            int ranb = IntegerUtils.IntegerReturns.IsEven(ran);
                            if (ranb != 0)
                            {
                                try
                                {
                                    splitdata[ran] = null;
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e.Message);
                                }
                            }
                            int sta2 = splitdata.Length;
                            if (ran == sta2)
                            {
                                
                                ranbool = true;
                            }
                            ran++;
                        }
                        Console.WriteLine(splitdata.Length);
                        //foreach (string str in splitdata){
                        //    if (str != null)
                        //    {
                        //        Console.WriteLine("STR="+str+"=STR");
                        //    }
                        //    count++;
                        //}
                        //splitdata array
                        //Index 0: Command
                        //Index 1: Argument 1
                        //Index 2: Argument 2
                        //Index 3: Argument 3....etc.....
                        Console.WriteLine("Processing:");
                        Console.WriteLine("  Command: " + splitdata[0]);
                        int specount = 1;
                        ArrayList argarray = new ArrayList();
                        foreach (string str in splitdata)
                        {
                            if (str != null)
                            {
                                if (count != 0)
                                {
                                    Console.WriteLine("  Argument " + specount + ": " + splitdata[count]);
                                    argarray.Add(splitdata[count]);
                                    specount++;
                                }
                            }
                            count++;
                        }
                        string[] ahh = new string[argarray.Count];
                        int i = 0;
                        foreach (object each in argarray)
                        {
                            ahh[i] = each.ToString();
                            i++;
                        }
                        string msgresponse = "Undefined";
                        switch (splitdata[0])
                        {
                            case "adduser":
                                //Add a user with arg1=username, arg2=password
                                try
                                {
                                    PrintValues(argarray);
                                    string usr = ahh[0];
                                    string pas = ahh[1];
                                    Console.WriteLine("Username: " + usr);
                                    Console.WriteLine("Password: " + pas);
                                    Daemon.Create.User(usr, pas);
                                    msgresponse = "Executed!";
                                } catch (Exception e){
                                    msgresponse = e.Message;
                                }
                                Console.WriteLine("adduser");
                                break;
                            case "deleteuser":
                                //Delete a user with arg1=username
                                try
                                {
                                Daemon.Delete.User(ahh[0]);
                                msgresponse = Daemon.Delete.response;
                                } catch (Exception e){
                                    msgresponse = e.Message;
                                }
                                Console.WriteLine("deleteuser");
                                break;
                        }
                        msg = Encoding.ASCII.GetBytes(msgresponse);
                    }
                    //Tell client command excepted.
                    //byte[] msg = Encoding.ASCII.GetBytes("yes");

                    handler.Send(msg);
                    TextTool.AdvWriteLine("Text sent : " + data, ConsoleColor.Red,true);
                    handler.Shutdown(SocketShutdown.Both);
                    handler.Close();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            TextTool.AdvWriteLine("\nPress ENTER to continue...", ConsoleColor.Red, true);
            Console.Read();
        }
        #endregion

        #region Main Function
        public static int Main(string[] args)
        {
            //Variables
            bool firsttime = false;
            //Setup first-time.
            #region First-Time Startup
            TextTool.AdvWriteLine("Starting Up Server Daemon...", ConsoleColor.Red, true);
            if (File.Exists(apppath + @"\server_files") == false)
            {
                //Setup Server Daemon
                //Directory.CreateDirectory(apppath + @"\server_files");
                Process crdir = new Process();
                crdir.StartInfo.FileName = "makedir";
                crdir.StartInfo.Arguments = "server_files";
                crdir.StartInfo.CreateNoWindow = false;
                crdir.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                crdir.Start();
                if (File.Exists(apppath + @"\server_files\data.sdf") == false)
                {
                    TextTool.AdvWriteLine(" Creating empty data files...", ConsoleColor.Red, true);
                    Process crdata = new Process();
                    crdata.StartInfo.FileName = "makefile";
                    crdata.StartInfo.Arguments = @"server_files\data.sdf";
                    crdata.StartInfo.CreateNoWindow = false;
                    crdata.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                    crdata.Start();
                    if (File.Exists(apppath + @"\server_files\data.sdf"))
                    {
                        TextTool.AdvWriteLine(" data.sdf exists and server-daemon is ready to start...", ConsoleColor.Red, true);
                    }
                    firsttime = true;
                }
                else
                {

                }
                if (File.Exists(apppath + @"\server_files\users.sdf") == false)
                {
                    TextTool.AdvWriteLine(" Creating empty users files...", ConsoleColor.Red, true);
                    Process crusers = new Process();
                    crusers.StartInfo.FileName = "makefile";
                    crusers.StartInfo.Arguments = @"server_files\users.sdf";
                    crusers.StartInfo.CreateNoWindow = false;
                    crusers.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                    crusers.Start();
                    if (File.Exists(apppath + @"\server_files\data.sdf"))
                    {
                        TextTool.AdvWriteLine(" users.sdf exists and server-daemon is ready to start...", ConsoleColor.Red, true);
                    }
                    firsttime = true;
                }
                else
                {

                }
            }
            else
            {
                if (File.Exists(apppath + @"\server_files\data.sdf") == false)
                {
                    //server_files exist but data.sdf doesn't exist.
                    TextTool.AdvWriteLine(" Missing data.sdf...", ConsoleColor.Red, true);
                    TextTool.AdvWriteLine(" Trying to fix data.sdf...", ConsoleColor.Red, true);

                }
                else
                {
                    //everything is fine...
                }
                if (File.Exists(apppath + @"\server_files\users.sdf") == false)
                {
                    //server_files exist but data.sdf doesn't exist.
                    TextTool.AdvWriteLine(" Missing users.sdf...", ConsoleColor.Red, true);
                    TextTool.AdvWriteLine(" Trying to fix users.sdf...", ConsoleColor.Red, true);
                }
                else
                {
                    //everything is fine...
                }
            }
#endregion
            //Setup Servers...
            #region Setup Servers
            if (firsttime == true)
            {
                //Setup Debug Server.
                //wait 3 seconds until  everything is fine...
                int wsec = 0; //timer
                int wsed = 0; //time + 3secs
                bool wbol = true;
                wsed = 3 - 1;
                while (wbol == true)
                {
                    if (wsec == wsed)
                    {
                        wbol = false;
                    }
                    wsec++;
                    TextTool.AdvWriteLine("waiting " + wsec, ConsoleColor.Red, true);
                    System.Threading.Thread.Sleep(1000);
                }
                //create debug user
                Daemon.Create.User("dbguser", "dbgpass");
                //create website
                Daemon.Create.Website("Debug Website", "dbgwebsite", "dbguser");
                //create directory
            }
            #endregion
            //Create Debug Website HTML
            #region Create Debug Website HTML
            if (firsttime == true)
            {
                Daemon.HTMLHandle.Make("dbgwebsite", "index", "<html>\r\n" +
                                                              "<body>\r\n" +
                                                              "Hello\r\n" +
                                                              "</body>\r\n" +
                                                              "</html>\r\n");
            }
            #endregion
            Daemon.Create.User("dbguser2", "dbgpass2");
            //Daemon.Delete.User("dbguser2");
            StartListening();
            return 0;
        }
        #endregion

        public static void PrintValues(IEnumerable myList)
        {
            foreach (Object obj in myList)
                Console.Write("   {0}", obj);
            Console.WriteLine();
        }
    }
    #endregion
    #region TextTool Class
    /// <summary>
    /// Contains static text methods.
    /// Put this in a separate class in your project.
    /// </summary>
    public static class TextTool
    {
        #region CountStringOccurrences
        /// <summary>
        /// Count occurrences of strings.
        /// </summary>
        public static int CountStringOccurrences(string text, string pattern)
        {
            // Loop through all instances of the string 'text'.
            int count = 0;
            int i = 0;
            while ((i = text.IndexOf(pattern, i)) != -1)
            {
                i += pattern.Length;
                count++;
            }
            return count;
        }
        #endregion

        #region AdvWriteLine
        /// <summary>
        /// Advanced Version of Console.WriteLine
        /// </summary>
        /// <param name="text">The value to write.</param>
        /// <param name="colour">The colour of the text.</param>
        public static void AdvWriteLine(string text, ConsoleColor colour, bool writetime)
        {
            ConsoleColor tempcolour = Console.ForegroundColor;
            Console.ForegroundColor = colour;
            if (writetime == false)
            {
                Console.WriteLine(text);
            }
            else if (writetime == true)
            {
                string temptime;
                temptime = "[" + DateTime.Now.Hour.ToString() + ":" + DateTime.Now.Minute.ToString() + ":" + DateTime.Now.Second.ToString() + "]";
                Console.WriteLine(temptime.ToString() + " " + text);
            }
            Console.ForegroundColor = tempcolour;
        }
        #endregion
    }
    #endregion
}
#endregion
